Using a file stream isn't mandatory—you can serialize
an object's state into any type of stream, such as a network or memory
stream.
Example 1. Serialization and deserialization using a memory stream
MyClass obj = new MyClass( );
obj.Number1 = 123;
IGenericFormatter formatter = new GenericBinaryFormatter( );
//Create a memory stream
Stream stream = new MemoryStream( );
using(stream)
{
formatter.Serialize(stream,obj);
obj = null;
stream.Position = 0; //Seek to the start of the memory stream
obj = formatter.Deserialize<MyClass>(stream);
}
Debug.Assert(obj.Number1 == 123);
|
You can actually use a memory stream to clone a serializable object, too. Example 2 shows the static Clone( ) method of the SerializationUtil static helper class.
Example 2. Cloning a serializable object
public static class SerializationUtil
{
static public T Clone<T>(T source)
{
Debug.Assert(typeof(T).IsSerializable);
IGenericFormatter formatter = new GenericBinaryFormatter( );
Stream stream = new MemoryStream( );
using(stream)
{
formatter.Serialize(stream,source);
stream.Seek(0,SeekOrigin.Begin);
T clone = formatter.Deserialize<T>(stream);
return clone;
}
}
//Rest of SerializationUtil
}
|
The Clone( ) method first verifies that
the object passed in for cloning is serializable, by obtaining the type
of the source object. The type Type provides a Boolean read-only property called IsSerializable, which returns true if the type has the Serializable attribute. Clone( ) then uses the GenericBinaryFormatter helper class to serialize and deserialize the object into and out of the memory stream. Clone( ) returns the deserialized object (in essence, a deep copy of the source object). Using Clone( ) is straightforward:
[Serializable]
public class MyClass
{...}
MyClass obj1 = new MyClass( );
MyClass obj2 = SerializationUtil.Clone(obj1);
You can use SerializationUtil.Clone( ) as an easy way to implement the ICloneable interface: |
|
[Serializable]
public class MyClass : ICloneable
{
public object Clone( )
{
return SerializationUtil.Clone(this);
}
}
1. Serializing Multiple Objects
A noteworthy aspect of using streams in
serialization is that there are no limits to the number of objects or
types you can serialize into a stream. It all depends on the way you
manage the stream and the sequence in which you write and read the
information. For example, to serialize additional objects into the same
stream, all you need to do is continue to write to the stream with the
formatter. Of course, you have to deserialize the objects in exactly the
same order in which you serialized them, as shown in Example 3. You can use the same formatter object or create a new one.
Example 3. Serializing multiple objects to the same stream
[Serializable]
public class MyClass
{...}
[Serializable]
public class MyOtherClass
{...}
MyClass obj1 = new MyClass( );
MyClass obj2 = new MyClass( );
MyOtherClass obj3 = new MyOtherClass( );
IGenericFormatter formatter = new GenericBinaryFormatter( );
Stream stream;
stream = new FileStream(@"C:\temp\obj.bin",FileMode.Create,FileAccess.Write);
using(stream)
{
formatter.Serialize(stream,obj1);
formatter.Serialize(stream,obj2);
formatter.Serialize(stream,obj3);
}
obj1 = obj2 = null;
obj3 = null;
//Later on:
stream = new FileStream(@"C:\temp\obj.bin",FileMode.Open,FileAccess.Read);
using(stream)
{
obj1 = formatter.Deserialize<MyClass>(stream);
obj2 = formatter.Deserialize<MyClass>(stream);
obj3 = formatter.Deserialize<MyOtherClass>(stream);
}
|
You can achieve a similar effect with memory
streams, too, as long as the memory stream automatically allocates
additional memory.
Another option is to append the state of
additional objects to an existing storage. In the case of a file stream,
open the file in append mode:
MyClass obj1 = new MyClass( );
MyClass obj2 = new MyClass( );
IGenericFormatter formatter = new GenericBinaryFormatter( );
//Create a new file
Stream stream;
stream = new FileStream(@"C:\temp\obj.bin",FileMode.Create,FileAccess.Write);
using(stream)
{
formatter.Serialize(stream,obj1);
}
//Append another object
stream = new FileStream(@"C:\temp\obj.bin",FileMode.Append,FileAccess.Write);
using(stream)
{
formatter.Serialize(stream,obj2);
}